#include "threadPool.h"
#include "userTable.h"
void *mkdir_c(void *arg, MYSQL *conn) {
  Para *para = (Para *)arg;

  pthread_mutex_lock(&para->pool->mutex);

  char *dirName = para->path[0]; //文件夹名
  printf("dirName is %s\n", dirName);
  char *userName = para->client->user_name; //用户名

  userInfo userInformation;
  user_table_find(para->pool->user_map, userName, &userInformation);
  char *virtualWorkPath =
      userInformation.virtual_path; //虚拟工作路径（最后不带/）
  printf("virtualWorkPath is %s\n", virtualWorkPath);
  int userId = userInformation.user_id; //用户id
  pthread_mutex_unlock(&para->pool->mutex);

  //虚拟路径拼接文件夹名得到本文件夹的虚拟路径
  char *virtualPath = (char *)calloc(
      strlen(virtualWorkPath) + strlen(dirName) + 2, sizeof(char));
  if (strcmp(virtualWorkPath, "/") == 0) {
    sprintf(virtualPath, "%s%s", virtualWorkPath, dirName);
  } else {
    sprintf(virtualPath, "%s/%s", virtualWorkPath, dirName);
  }

  // 获得父级路径的id
  char bufSql[1000] = {0};
  int parentId = -1;
  sprintf(bufSql, "select * from vfs where user_id=%d and file_path='%s' ",
          userId, virtualWorkPath);
  mysql_query(conn, bufSql);
  MYSQL_RES *result = mysql_store_result(conn);
  MYSQL_ROW row;
  if ((row = mysql_fetch_row(result))) {
    parentId = atoi(row[0]);
  }
  mysql_free_result(result);

  //查询vfs表检查当前目录下是否已存在该文件夹
  bzero(bufSql, sizeof(bufSql));
  sprintf(bufSql,
          "select * from vfs where file_name='%s' and file_type='d' and "
          "parent_id=%d and user_id=%d",
          dirName, parentId, userId); //该记录的名字是文件夹名
  mysql_query(conn, bufSql);
  result = mysql_store_result(conn);
  uint64_t rowNum = mysql_num_rows(result);

  if (rowNum != 0) {
    char failedRet[] = "ERROR: Directory already exists!\n";
    send_tlv(para->netfd, failedRet, strlen(failedRet));
    mysql_free_result(result);
    return NULL;
  }
  mysql_free_result(result);

  //插入记录就相当于新建文件夹了
  bzero(bufSql, sizeof(bufSql));
  sprintf(
      bufSql,
      "INSERT INTO vfs (file_name, parent_id, file_type, user_id, file_path) "
      "VALUES ('%s', %d, 'd', %d, '%s')",
      dirName, parentId, userId, virtualPath);
  mysql_query(conn, bufSql);
  result = mysql_store_result(conn);
  mysql_free_result(result);
  char SuccessRet[] = "Directory created.\n";
  send_tlv(para->netfd, SuccessRet, strlen(SuccessRet));
  memset(SuccessRet, 0, sizeof(SuccessRet));
  free(virtualPath);

  return NULL;
}
void *pwd_c(void *arg, MYSQL *conn) {
  printf("in pwd\n");
  Para *para = (Para *)arg;

  pthread_mutex_lock(&para->pool->mutex);

  char *userName = para->client->user_name; //用户名

  userInfo userInformation;
  user_table_find(para->pool->user_map, userName, &userInformation);
  char *virtualWorkPath =
      userInformation.virtual_path; //虚拟工作路径（最后不带/）

  char ret[1024] = {0};
  strcpy(ret, "Path is :");
  strcat(ret, virtualWorkPath);
  printf("ret=%s\n", ret);
  send_tlv(para->netfd, ret, strlen(ret));
  pthread_mutex_unlock(&para->pool->mutex);
  return NULL;
}
void *ls_c(void *arg, MYSQL *conn) {
  Para *para = (Para *)arg;
  pthread_mutex_lock(&para->pool->mutex);
  char *userName = para->client->user_name; //用户名
  userInfo userInformation;

  user_table_find(para->pool->user_map, userName, &userInformation);
  char *virtualWorkPath =
      userInformation.virtual_path;     //虚拟工作路径（最后不带/）
  int userId = userInformation.user_id; //用户id
  pthread_mutex_unlock(&para->pool->mutex);
  // 获得用户虚拟工作路径的id
  char bufSql[1000] = {0};
  int parentId = -1;
  bzero(bufSql, sizeof(bufSql));
  sprintf(bufSql, "select * from vfs where user_id=%d and file_path='%s' ",
          userId, virtualWorkPath);
  mysql_query(conn, bufSql);
  MYSQL_RES *result = mysql_store_result(conn);
  MYSQL_ROW row;
  if ((row = mysql_fetch_row(result))) {
    parentId = atoi(row[0]);
  }
  mysql_free_result(result);
  //查询父路径是用户虚拟工作路径的所有文件和文件夹
  bzero(bufSql, sizeof(bufSql));
  sprintf(bufSql, "select * from vfs where parent_id=%d", parentId);
  int queryRet = mysql_query(conn, bufSql);
  if (queryRet == -1) {
    // 查询失败
    char errorMsg[] = "ERROR: Database query failed.\n";
    send_tlv(para->netfd, errorMsg, strlen(errorMsg));
    return NULL;
  }
  result = mysql_store_result(conn);
  if (result == NULL) {
    // 存储结果失败
    char errorMsg[] = "ERROR: Failed to store result.\n";
    send_tlv(para->netfd, errorMsg, strlen(errorMsg));
    return NULL;
  }
  my_ulonglong rowNum = mysql_num_rows(result);
  char fileList[1024] = {0}; //存当前目录下文件名和文件夹名
  if (rowNum > 0) {
    MYSQL_ROW row;
    while ((row = mysql_fetch_row(result))) {
      printf("4\n");
      strcat(fileList, row[1]);
      strcat(fileList, "  ");
    }
  }
  mysql_free_result(result);
  //向客户端返回查找结果
  if (strlen(fileList) > 0) {
    send_tlv(para->netfd, fileList, strlen(fileList));
  } else {
    char failedRet[] = "No file exist in this path.\n";
    send_tlv(para->netfd, failedRet, strlen(failedRet));
  }
  return NULL;
}
void *cd_c(void *arg, MYSQL *conn) {
  Para *para = (Para *)arg;
  pthread_mutex_lock(&para->pool->mutex);
  char *userName = para->client->user_name; //用户名

  userInfo userInformation;

  user_table_find(para->pool->user_map, userName, &userInformation);
  char *virtualWorkPath =
      userInformation.virtual_path;     //虚拟工作路径（最后不带/）
  int userId = userInformation.user_id; //用户id

  //用户发来的命令是"cd ."或"cd /"
  if ((strcmp(para->path[0], ".") == 0 || strcmp(para->path[0], "/") == 0) &&
      strlen(para->path[0]) == 1) { //用户发来的命令是"cd"或"cd /"
    strcpy(userInformation.virtual_path, "/");
    char rootRet[] = "In root now\n";
    send_tlv(para->netfd, rootRet, strlen(rootRet));
    return NULL;
  }
  pthread_mutex_unlock(&para->pool->mutex);
  //将用户发来的参数转化为绝对路径
  char absolutePath[1024] = {0};
  if (strcmp(para->path[0], "/") == 0) {
    strcpy(absolutePath, para->path[0]); // 用户发来的是绝对路径
  } else {
    // 用户发来的是相对路径
    if (strcmp(virtualWorkPath, "/") == 0) {
      sprintf(absolutePath, "%s%s", virtualWorkPath, para->path[0]);
    } else {
      sprintf(absolutePath, "%s/%s", virtualWorkPath, para->path[0]);
    }
  }
  printf("absolutePath is %s\n", absolutePath);
  char *stack[1024]; // 指针数组栈
  int stackSize = 0; // 栈的大小

  //将虚拟工作路径按 / 分割后压入栈中
  stack[stackSize++] = "/"; //栈底是根目录

  // 化简目标路径并判断是否合法
  char *token = strtok(absolutePath, "/");
  while (token != NULL) {
    if (strcmp(token, "..") == 0) {
      if (stackSize == 1) {
        // 已经到达根目录，无法再向上跳
        char failedRet[] = "Error:Can not go beyond root directory";
        send_tlv(para->netfd, failedRet, strlen(failedRet));
        return NULL;
      }
      stackSize--; // 弹出栈顶元素
    } else if (strcmp(token, ".") != 0) {
      // 普通目录名压入栈中,遇到 "." 时忽略
      stack[stackSize++] = token;
    }
    token = strtok(NULL, "/");
  }
  char newPath[1024] = {0};
  newPath[0] = '/';
  for (int i = 1; i < stackSize; i++) {
    if (strcmp(stack[i], "/") != 0) {
      strcat(newPath, stack[i]);
    }
    if (i != stackSize - 1) {
      strcat(newPath, "/");
    }
  }
  // 查询路径是否存在
  char bufSql[4096] = {0};
  sprintf(
      bufSql,
      "select * from vfs where user_id=%d and file_path='%s' and file_type='d'",
      userId, newPath);
  if (mysql_query(conn, bufSql)) {
    // 查询失败
    char errorMsg[] = "ERROR: Database query failed.\n";
    send_tlv(para->netfd, errorMsg, strlen(errorMsg));
    return NULL;
  }
  MYSQL_RES *result = mysql_store_result(conn);
  if (result == NULL) {
    // 存储结果失败
    char errorMsg[] = "ERROR: Failed to store result.\n";
    send_tlv(para->netfd, errorMsg, strlen(errorMsg));
    return NULL;
  }
  if (mysql_num_rows(result) == 0) {
    // 路径不存在
    printf("3\n");
    char failedRet[] = "ERROR: Path does not exist.\n";
    send_tlv(para->netfd, failedRet, strlen(failedRet));
    mysql_free_result(result);
    return NULL;
  }
  mysql_free_result(result);

  // 路径验证通过，更新用户虚拟工作路径
  pthread_mutex_lock(&para->pool->mutex);
  strcpy(userInformation.virtual_path, newPath);
  char successRet[] = "SUCCESS: Path changed.\n";
  send_tlv(para->netfd, successRet, strlen(successRet));
  memset(successRet, 0, sizeof(successRet));
  pthread_mutex_unlock(&para->pool->mutex);
  return NULL;
}